package com.fingard.dsp.bank.directbank.icbc02;

import com.alibaba.fastjson.JSONObject;
import com.fingard.dsp.bank.directbank.bankInterface.IAcceptNotice;
import com.fingard.generalobj.NoticeReq;
import com.fingard.generalobj.NoticeResp;
import com.fingard.net.listener.SocketReceiver;
import com.fingard.text.Base64Helper;
import com.fingard.xml.XElement;
import com.fingard.xml.XmlTextReader;

import sun.misc.BASE64Decoder;

public class ICBC02AcceptNotice extends ICBC02Base implements IAcceptNotice {
    @Override
    public NoticeResp dealNotice(NoticeReq pNtReq) throws Exception {
    	NoticeResp resp = new NoticeResp();
        try {
            //获取银行通知的数据区分业务类别 做身份验证
            //直接把数据用json格式推送给ATS 返回输出流数据返回给银行表示数据接收成功
            //https://客户ERP服务器的地址和端口号 115.238.104.98 8090
            //Version=版本号（目前支持0.0.0.1和0.0.1.0两个版本。不同版本号对应的接口格式不同，请参考具体交易的接口文档)
            // &TransCode=交易代码（区分交易类型，每个交易固定)&BankCode=客户的归属单位&GroupCIS=客户的归属编码
            // &ID=客户的证书ID（无证书客户可空)&PackageID=客户的指令包序列号（由客户ERP系统产生，不可重复)
            // &reqData=银行主动返回给客户的xml请求数据
            //模拟返回的数据
            /*p_req = "Version=0.0.1.0&TransCode=LITOPN&ID=12378&reqData=<?xml version=\"1.0\" encoding = \"GBK\"?>\n" +
                    "\t<CMS>\n" +
                    "\t\t<eb>\n" +
                    "\t\t\t<pub>\n" +
                    "\t\t\t\t<TransCode>LITOPN</TransCode>\n" +
                    "\t\t\t\t<CIS>集团编号</CIS>\n" +
                    "\t\t\t\t<BankCode>银行编码</BankCode>\n" +
                    "\t\t\t\t<TranDate>交易日期</TranDate>\n" +
                    "\t\t\t\t<TranTime>交易时间</TranTime>\n" +
                    "\t\t\t\t<fSeqno>指令包序列号</fSeqno>\n" +
                    "\t\t\t\t<RetCode>00000</RetCode>\n" +
                    "<RetMsg>交易成功</RetMsg>\n" +
                    "\t\t\t</pub>\n" +
                    "\t\t\t<out>\n" +
                    "<TranSerialNo>银行交易流水号</TranSerialNo>\n" +
                    "<CorpDate>企业交易日期</CorpDate>\n" +
                    "\t\t\t\t<CorpTime>企业交易时间</CorpTime>\n" +
                    "<BankDate>银行交易日期</BankDate>\n" +
                    "\t\t\t\t<BankTime>银行交易时间</BankTime>\n" +
                    "\t\t\t\t<HeadCIS>企业集团总部CIS</HeadCIS>\n" +
                    "\t\t\t\t<BankCompanyId>银行公司编号</BankCompanyId>\n" +
                    "<BankBchCode>协办行地区号</BankBchCode>\n" +
                    "<BankBchNo>协办行网点号</BankBchNo>\n" +
                    "<BankOrgCode>承办行地区号</BankOrgCode>\n" +
                    "<BankOrgNo>承办行网点号</BankOrgNo>\n" +
                    "<Remark>备注</Remark>\n" +
                    "<LCNo>信用证号码</LCNo>\n" +
                    "<CorpInCode>交易集团编号</CorpInCode>\n" +
                    "<AppNameAddr>申请人名址</AppNameAddr>\n" +
                    "<BenNameAddr>受益人名址</BenNameAddr>\n" +
                    "<OpenDate>开证日期</OpenDate>\n" +
                    "<LCCurrCode>信用证币种</LCCurrCode>\n" +
                    "<LCAmt>信用证金额</LCAmt>\n" +
                    "<AdvNameAddr>通知行名址</AdvNameAddr>\n" +
                    "<RepReserved1>响应备用字段1</RepReserved1>\n" +
                    "<RepReserved2>响应备用字段2</RepReserved2>\n" +
                    "<rd>\n" +
                    "<Mesg>信用证电文稿</Mesg>\n" +
                    "<RepReserved3>响应备用字段3</RepReserved3>\n" +
                    "<RepReserved4>响应备用字段4</RepReserved4>\n" +
                    "</rd>\n" +
                    "\t\t\t</out>\n" +
                    "\t\t</eb>\n" +
                    "\t</CMS>\n";*/
        	String p_req = pNtReq.getReqString();
        	WriteBankLogLn("接收到请求：" + pNtReq.getFullString());
        	
            String reqData = "";//银行返回的实际数据
            String xmlData = "";//xml数据
            StringBuilder sb = new StringBuilder();
            XmlTextReader tmpBkReader = null;
            StringBuilder msg = new StringBuilder();
            if (p_req.indexOf("TransCode") != -1) {
                int one = p_req.indexOf("&");
                int two = p_req.indexOf("&", one + 1);
                String transCode = p_req.substring(p_req.indexOf("TransCode=") + 10, two);
                reqData = p_req.substring(p_req.lastIndexOf("&reqData=") + 9);
                //todo 可能要特别处理 也可能不需要签名直接取
                xmlData = doSign(reqData,false);
                WriteBankLogLn("银行返回的原文数据:"+xmlData);
                tmpBkReader = loadBankRespXmlReader(xmlData, msg);
                if(tmpBkReader!=null) {
                    String transType = "";
                    String retCode = tmpBkReader.getFirstText("/CMS/eb/pub/RetCode");
                    String retMsg = tmpBkReader.getFirstText("/CMS/eb/pub/RetMsg");
                    JSONObject json = new JSONObject();
                    TransTypeEnum transTypeEnum = null;
                    if (isActiveRetCode(retCode)) {
                        while (tmpBkReader.read("/CMS/eb/out")) {
                            XElement xElement = tmpBkReader.readedXElement;
                            transTypeEnum = switchEnum(transCode);
                            if (transTypeEnum != null) {
                                switchData(transTypeEnum, sb, json, xElement, transCode, transType, retMsg);
                            }
                        }
                    } else {
                        sb.append("transtype=default&data={\"response\":\"-1\",\"responseinfo\":\"" + retMsg + "\"}");
                    }
                }else {
                    WriteBankLogLn(msg.toString());
                }
            } else {
                sb.append("transtype=default&data={\"response\":\"-1\",\"responseinfo\":\"银行推送数据无TransCode参数信息\"}");
            }
            String[] tmp = sendToATS(sb.toString());
            if(tmp[0].length()==0){
                WriteBankLogLn("推送数据到ATS成功:"+tmp[1]);
            }else {
                WriteBankLogLn("推送数据到ATS失败"+tmp[1]);
            }
            String tmpStrRet = "ok";
            WriteBankLogLn("响应："+tmpStrRet);
            resp.respBytes = tmpStrRet.getBytes(pNtReq.reqCharset);
        	return resp;
        } catch (Exception e) {
            e.printStackTrace();
            WriteBankLogLn(e.getMessage());
        }
        String tmpStrRet = "false";
        WriteBankLogLn("响应："+tmpStrRet);
        resp.respBytes = tmpStrRet.getBytes(pNtReq.reqCharset);
    	return resp;
    }

    //匹配银行推送数据
    public void switchData(TransTypeEnum transTypeEnum, StringBuilder sb, JSONObject json, XElement xElement, String transCode, String transType, String retMsg) throws Exception {
        switch (transTypeEnum) {
            case LITOPN://开证申请
            case LITAME://开证修改申请
                //开证/开证申请通知：transtype=LCIssueInfo&data={"response":"0","responseinfo":"接收成功",transSeqID:"交易流水号","LCNo":"信用证编号","Message":"<xml></xml>","Remark":"备注","OpenDate":"开证日期"}
                if (transCode.equals("LITOPN")) {
                    transType = "LCIssueInfo";
                } else if (transCode.equals("LITAME")) {
                    transType = "LCIssueEditInfo";
                }
                sb.append("transtype=" + transType + "&data=");
                json.put("Response", "0");
                json.put("Responseinfo", retMsg);
                json.put("TransSeqID", xElement.getSingleTextNotNull("TranSerialNo"));
                json.put("LCNo", xElement.getSingleTextNotNull("LCNo"));
                json.put("Message", xElement.getSingleTextNotNull("Mesg"));
                json.put("Remark", xElement.getSingleTextNotNull("Remark"));
                json.put("OpenDate", xElement.getSingleTextNotNull("OpenDate"));
                sb.append(json.toString());
                break;
            case LITDIS://不符点通知
            case LITFRE://点提不符点接受报文
                //做数据解密 如果是密文的话 拼接数据给ATS
                //不符点通知/点提不符点接受报文：transtype=DisInfo&data={"Response":"0","Responseinfo":"接收成功",TransSeqID:"交易流水号","LCNo":"信用证编号","BRNo":"业务BR编号","DisDate":"电提日期"，"BillCurrCode":"电提单据币种","BillAmt":"电提单据金额","Message":"不符点内容","Remark":"备注"}
                if (transCode.equals("LITDIS")) {
                    transType = "DisInfo";
                } else if (transCode.equals("LITFRE")) {
                    transType = "DisAcceptInfo";
                }
                sb.append("transtype=" + transType + "&data=");
                json.put("Response", "0");
                json.put("Responseinfo", retMsg);
                json.put("TransSeqID", xElement.getSingleTextNotNull("TranSerialNo"));
                json.put("LCNo", xElement.getSingleTextNotNull("LCNo"));
                json.put("BRNo", xElement.getSingleTextNotNull("BRNo"));
                json.put("DisDate", xElement.getSingleTextNotNull("DisDate"));
                json.put("BillCurrCode", xElement.getSingleTextNotNull("BillCurrCode"));
                json.put("BillAmt", xElement.getSingleTextNotNull("BillAmt"));
                json.put("Message", xElement.getSingleTextNotNull("DisMesg"));
                json.put("Remark", xElement.getSingleTextNotNull("Remark"));
                sb.append(json.toString());
                break;
            case LITDCK://来单通知书
            case LITTRA://电索通知书
                //transtype=OrderInfo&data={"Response":"0","Responseinfo":"接收成功",TransSeqID:"交易流水号","LCNo":"信用证编号","BRNo":"业务BR编号","ComBillDate":"来单日期"，"BillCurrCode":"电提单据币种","BillAmt":"电提单据金额"，"PayTotalAmt":"付款总金额"
                //,"OrderType":"来单类型1.来单通知2.电索通知","Message":"不符点内容","DraftTermDays":"付款期限yy-mm-dd","AcptPayTerm":"最迟确认期限","PayDueDate":"付款到期日","ContractNo":"合同号","InvNo":"发票号","DraftPayType":"汇票付款类型","Remark":"备注"}
                String orderType = "";
                if (transCode.equals("LITDCK")) {
                    transType = "OrderInfo";
                    orderType = "1";
                } else if (transCode.equals("LITTRA")) {
                    transType = "CableInfo";
                    orderType = "2";
                }
                sb.append("transtype=" + transType + "&data=");
                json.put("Response", "0");
                json.put("Responseinfo", retMsg);
                json.put("TransSeqID", xElement.getSingleTextNotNull("TranSerialNo"));
                json.put("LCNo", xElement.getSingleTextNotNull("LCNo"));
                json.put("BRNo", xElement.getSingleTextNotNull("BRNo"));
                json.put("ComBillDate", xElement.getSingleTextNotNull("ComBillDate"));
                json.put("BillCurrCode", xElement.getSingleTextNotNull("BillCurrCode"));
                json.put("BillAmt", xElement.getSingleTextNotNull("BillAmt"));
                json.put("PayTotalAmt", xElement.getSingleTextNotNull("PayTotalAmt"));
                json.put("PayCurrCode", xElement.getSingleTextNotNull("PayCurrCode"));
                json.put("OrderType", orderType);
                json.put("Message", xElement.getSingleTextNotNull("Dis"));//Todo 暂时取不符点 可能需要解析
                json.put("DraftTermDays", xElement.getSingleTextNotNull("DraftTermDays"));//Todo 银行返回的只有四位
                json.put("AcptPayTerm", xElement.getSingleTextNotNull("AcptPayTerm"));//承兑/付款最迟期限
                json.put("PayDueDate", xElement.getSingleTextNotNull("PayDueDate"));
                json.put("ContractNo", xElement.getSingleTextNotNull("ContractNo"));
                json.put("InvNo", xElement.getSingleTextNotNull("InvNo"));
                json.put("DraftPayType", xElement.getSingleTextNotNull("DraftPayType"));
                json.put("Remark", xElement.getSingleTextNotNull("Remark"));
                sb.append(json.toString());
                break;
            case LITAMB://来单修改通知
            case LITACP://来单承兑确认
            case LITACM://来单承兑修改确认
            case LITREJ://拒付
            case LITRTN://退单
                if (transCode.equals("LITAMB")) {
                    transType = "OrderEditInfo";
                } else if (transCode.equals("LITACP")) {
                    transType = "OrderHonourInfo";
                } else if (transCode.equals("LITACM")) {
                    transType = "HonourEditInfo";
                } else if (transCode.equals("LITREJ")) {
                    transType = "DishonorConfirm";
                } else if (transCode.equals("LITRTN")) {
                    transType = "ChargeBackApplyInfo";
                }
                sb.append("transtype=" + transType + "&data=");
                json.put("Response", "0");
                json.put("Responseinfo", retMsg);
                json.put("TransSeqID", xElement.getSingleTextNotNull("TranSerialNo"));
                sb.append(json.toString());
                break;
            case LITSET://付款通知书 感觉和来单修改相同 无用信息
                if(transCode.equals("LITSET")){
                    transType = "PayInfo";
                }
                sb.append("transtype=" + transType + "&data=");
                json.put("Response", "0");
                json.put("Responseinfo", retMsg);
                json.put("TransSeqID", xElement.getSingleTextNotNull("TranSerialNo"));
                sb.append(json.toString());
                break;
            default:
                transType = "otherInfo";
                sb.append("transtype=" + transType + "&data=");
                json.put("Response", "0");
                json.put("Responseinfo", "未知流程通知数据，流程名称为:"+transCode);
                json.put("TransSeqID", xElement.getSingleTextNotNull("TranSerialNo"));
                sb.append(json.toString());
                break;
        }
    }

    public String doSign(String respData,boolean p_doSign){
        try {
            if (p_doSign) {
                byte[] data = new BASE64Decoder().decodeBuffer(respData);
                byte[] len_byte = new byte[10];//原文长度
                System.arraycopy(data,0,len_byte,0,10);
                int srcLength = Integer.parseInt(new String(len_byte));
                byte[] src_byte = new byte[srcLength];//原文
                System.arraycopy(data,10,src_byte,0,srcLength);
                byte[] encry_byte = new byte[data.length-10-srcLength];//密文
                System.arraycopy(data,10+srcLength,encry_byte,0,data.length-10-srcLength);
                respData = new String(src_byte);
            }else {
                respData = Base64Helper.getFromBase64(respData,getCharset());
            }
        }catch (Exception e){
            e.printStackTrace();
            WriteBankLogLn(e.getMessage());
        }
        return respData;
    }
    enum TransTypeEnum {
        LITOPN, LITAME, LITDIS, LITFRE, LITDCK, LITAMB, LITACP, LITACM, LITREJ, LITRTN, LITSET, LITTRA;
    }

    public TransTypeEnum switchEnum(String transCode) {
        TransTypeEnum transTypeEnum = null;
        // LITOPN, LITAME, LITDIS, LITFRE, LITDCK, LITAMB, LITACP, LITACM, LITREJ, LITRTN, LITSET, LITTRA;
        if (transCode.equals("LITOPN")) {
            transTypeEnum = TransTypeEnum.LITOPN;
        }else if(transCode.equals("LITAME")){
            transTypeEnum = TransTypeEnum.LITAME;
        }else if(transCode.equals("LITDIS")){
            transTypeEnum = TransTypeEnum.LITDIS;
        }else if(transCode.equals("LITFRE")){
            transTypeEnum = TransTypeEnum.LITFRE;
        }else if(transCode.equals("LITDCK")){
            transTypeEnum = TransTypeEnum.LITDCK;
        }else if(transCode.equals("LITAMB")){
            transTypeEnum = TransTypeEnum.LITAMB;
        }else if(transCode.equals("LITACP")){
            transTypeEnum = TransTypeEnum.LITACP;
        }else if(transCode.equals("LITACM")){
            transTypeEnum = TransTypeEnum.LITACM;
        }else if(transCode.equals("LITREJ")){
            transTypeEnum = TransTypeEnum.LITREJ;
        }else if(transCode.equals("LITRTN")){
            transTypeEnum = TransTypeEnum.LITRTN;
        }else if(transCode.equals("LITSET")){
            transTypeEnum = TransTypeEnum.LITSET;
        }else if(transCode.equals("LITTRA")){
            transTypeEnum = TransTypeEnum.LITTRA;
        }
        return transTypeEnum;
    }

    @Override
    public void getContentLength(SocketReceiver p_receiver) throws Exception {

    }
}


